<template>
  <div class="login-content">
    <div class="login-panel" v-if="firstNeedUpdatePwd !== 1">
      <div class="login-title">云雀智能体集群视频分析平台</div>
      <el-form ref="ruleFormRef" :rules="loginRules" :model="form">
        <el-form-item prop="userName">
          <el-input v-model="form.userName" @input="nameChange" class="input-panel name" placeholder="请输入用户名">
            <template #prefix>
              <img :src="smile"/>
            </template>
          </el-input>
        </el-form-item>
        <div class="error-input" :style="[errorInput? '':'visibility: hidden;']" v-text="errorInput"></div>
        <el-form-item prop="userKey">
          <el-input v-model="form.userKey"
                    :type="flag? 'text' :'password'"
                    @input="passwordChange"
                    class="input-panel userKey"
                    placeholder="请输入密码">
            <template #prefix>
              <img :src="lock"/>
            </template>
            <template #suffix>
              <img :src="flag? hidden : visible" @click="flag= !flag" />
            </template>
          </el-input>
        </el-form-item>
        <el-form-item prop="verifyCode" v-if="verifyCodeShow">
          <el-input v-model="form.verifyCode" class="input-panel verifyCode" @input="verifyCodeChange" placeholder="请输入验证码">
            <template #append><img :src="'data:image/png;base64,' + verificationCode" @click="changeCode" alt=""/>
            </template>
          </el-input>
        </el-form-item>
        <div class="operation">
          <el-checkbox v-model="storeCipher" label="记住密码" />
          <div class="tips">忘记密码，请联系管理员</div>
        </div>
        <el-form-item>
          <el-button type="primary" @click="loginButton(ruleFormRef)">登录</el-button>
        </el-form-item>
      </el-form>
    </div>

    <div class="login-first" v-if="firstNeedUpdatePwd === 1">
      <div class="tips">首次登录请设置密码：</div>
      <div class="tips">密码长度为<span class="highlight">{{passWordConfig.length}}-32位</span>，必须包含
        <template v-for="str in pwdStrCheckList.filter(pwd=>passWordConfig.charCheck?.some(char=>char===pwd.id))" :key="str.id">
          “<span class="highlight">{{str.name}}</span>”
        </template>,

      </div>
      <el-form ref="resetFormRef" :rules="resetRules" :model="firstForm">
        <el-form-item prop="newPassword">
          <el-input v-model="firstForm.newPassword"
                    @input="passwordChange"
                    :type="flagNew? 'text' :'password'"
                    class="input-panel newPassword"
                    placeholder="请输入新密码">
            <template #suffix>
              <img :src="flagNew? hidden : visible" @click="flagNew= !flagNew"/>
            </template>
          </el-input>
        </el-form-item>
        <el-form-item prop="secondPassword">
          <el-input v-model="firstForm.secondPassword"
                    @input="passwordChange"
                    :type="flagSecond? 'text' :'password'"
                    class="input-panel secondPassword"
                    placeholder="请再次输入新密码">
            <template #suffix>
              <img :src="flagSecond? hidden : visible" @click="flagSecond= !flagSecond" />
            </template>
          </el-input>
        </el-form-item>
        <div class="error-input" :style="[errorInput? '':'visibility: hidden;']" v-text="errorInput"></div>
        <el-form-item>
          <el-button @click="cancelReset">取消</el-button>
          <el-button type="primary" @click="reset(resetFormRef)">登录</el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>
<script setup>
import {getCurrentInstance, onBeforeUnmount, onMounted, reactive, toRefs} from "vue";
import {useRouter} from "vue-router"
import CryptoJS from 'crypto-js';
import lock from '../../assets/img/login/lock.png'
import smile from '../../assets/img/login/smile.png'
import hidden from '../../assets/img/login/hidden.png'
import visible from '../../assets/img/login/visible.png'
import {solarPowerSystem} from '../projectAlias.js'

import useUserMessage from "@/store/userMessage.js";
const userMessage = useUserMessage();
const {proxy} = getCurrentInstance();
const router = useRouter();
const state = reactive({
  flag: false,//密码小眼睛展示，不涉及数据
  ruleFormRef: null,

  form:{
    userName: '',
    userKey: null,
    projectAlias: solarPowerSystem,
  },
  loginRules:{
    userName: [
      {required: true, message: '请输入用户名', trigger: 'change'},
    ],
    userKey: [
      {required: true, message: '请输入密码', trigger: 'change'}
    ]
  },
  errorInput: null, //错误信息
  verificationCode: '', //验证码
  verifyCodeShow: false, //启动验证码的标志
  storeCipher: false,
  passWordConfig:{
    //密码最短长度
    length:null,
    //包含项
    charCheck:[]
  },//安全配置密码配置
  pwdStrCheckList:[
    {
      name:'大写字母',
      id:1
    },
    {
      name:'小写字母',
      id:2
    },
    {
      name:'数字',
      id:3
    },
    {
      name:'特殊字符',
      id:4
    },
  ],//密码字符串校验

  firstNeedUpdatePwd: 2,//首次登录修改密码 1
  flagNew: false,//密码小眼睛展示，不涉及数据
  flagSecond: false,//密码小眼睛展示，不涉及数据
  resetFormRef:null,
  firstForm: {
    newPassword: null,
    secondPassword: null,
  },
  resetRules:{
    newPassword: [
      {required: true, message: '请输入新密码', trigger: 'change'},
    ],
    secondPassword: [
      {required: true, message: '请再次输入新密码', trigger: 'change'}
    ]
  },
})
const methods = {
  /**
   * 登录判断
   * @returns {boolean}
   */
  loginButton(ref) {
    if (!ref) return
    ref.validate((valid) => {
      if (!valid) return
      if (verifyCodeShow.value && form.value.verifyCode === '') {
        proxy.$tipMessage('请填写验证码', 'error')
        return
      }

      //aes cbc  加密
      let param = Object.assign({}, form.value)
      let key = CryptoJS.enc.Utf8.parse(import.meta.env.VITE_AES_CBC_KEY)
      let iv = CryptoJS.enc.Utf8.parse(import.meta.env.VITE_AES_CBC_IV)
      let name = CryptoJS.AES.encrypt(form.value.userName, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.ZeroPadding
      });
      param.userName = name.toString();
      let pass = CryptoJS.AES.encrypt(form.value.userKey, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.ZeroPadding
      });
      param.userKey = pass.toString();

      proxy.$http.postLoginWithBody('login/loginSecurity', param)
          .then(async (res) => {
            userMessage.setMessage(res);

            //密码加密
            let base = window.btoa(form.value.userKey)
            let cipher = localStorage.storeCipher ? JSON.parse(localStorage.storeCipher) : {};
            if (storeCipher.value) {
              cipher[form.value.userName] = base;
              localStorage.storeCipher = JSON.stringify(cipher);
            } else if (cipher.hasOwnProperty(form.value.userName)) {
              delete cipher[form.value.userName]
            }

            if (res.firstNeedUpdatePwd === 1) {
              firstNeedUpdatePwd.value = res.firstNeedUpdatePwd;
              await methods.getPassWordConfig(); //请求安全设置详情
              return
            }
            methods.jumpPage();
          }).catch((error) => {
        errorInput.value = error.data.error_msg;
        if (error.data.error_code === '1017') verifyCodeShow.value = true;
        console.log('登录失败', error)
      })
    })
  },

  /**
   * 监听用户名修改问题
   */
  nameChange(value){
    let cipher = localStorage.storeCipher ? JSON.parse(localStorage.storeCipher) : {};
    if (cipher.hasOwnProperty(value)){
      storeCipher.value = true;
      form.value.userKey = window.atob(cipher[value]);
    }
    errorInput.value = null;
  },

  /**
   * 密码输入框修改,三个密码框的方法
   */
  passwordChange(){
    errorInput.value = null;
  },

  /**
   * 验证码框
   */
  verifyCodeChange(){
    errorInput.value = null;
  },

  /**
   * 取消修改密码
   */
  cancelReset(){
    methods.jumpPage();
  },

  /**
   * 首次修改密码接口
   */
  reset(ref) {
    if (!ref) return;
    ref.validate((valid) => {
      if (!valid) return false;
      if (firstForm.value.newPassword !== firstForm.value.secondPassword) {
        errorInput.value = '密码不一致'
        return
      }

      //aes cbc  加密
      let key = CryptoJS.enc.Utf8.parse(import.meta.env.VITE_AES_CBC_KEY)
      let iv = CryptoJS.enc.Utf8.parse(import.meta.env.VITE_AES_CBC_IV)
      let newPassword = CryptoJS.AES.encrypt(firstForm.value.newPassword, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.ZeroPadding
      });

      proxy.$http.getLoginWithUrl('system/user/firstChangePwdSecurity', {
        newPassword: newPassword.toString()
      }).then(() => {
        methods.jumpPage();
      }).catch((error) => {
        errorInput.value = error.data.error_msg;
        console.log('登录失败', error)
      })
    })
  },

  /**
   * 跳转页面
   */
  jumpPage(){
    router.push('/');
  },

  /**
   * 获取安全详情
   * @returns {Promise<void>}
   */
  async getPassWordConfig() {
    try {
      const {passwordCheck} = await methods.getSafeConfigDetail()
      state.passWordConfig = passwordCheck
    } catch (e) {
      console.log(e)
    }
  },

  //获取安全设置列表
  getSafeConfigDetail:params=>{
    return proxy.$http.getLoginWithUrl('system/safeconfig/detail',params)
  },


  /**
   * 回车登录
   * @param event
   */
  enterKeyDown(event) {
    if (event['keyCode'] === 13 && firstNeedUpdatePwd.value !== 1) {
      methods.loginButton(ruleFormRef.value);
    }else if (event['keyCode'] === 13 && firstNeedUpdatePwd.value === 1){
      methods.jumpPage();
    }
  },

  /**
   * 获取图片验证码
   */
  getCaptcha() {
    proxy.$http.postLoginWithBody('login/getCaptcha', {
      imageWidth: 120,
      imageHeight: 30,
      lineCount: 15,
      number: 6
    }).then((res) => {
      verificationCode.value = res;
    }).catch((error) => {
      console.log(error)
    })
  },

  changeCode(){
    methods.getCaptcha();
  },
}

const {
  flag,
  form,
  errorInput,
  storeCipher,
  firstForm,
  loginRules,
  ruleFormRef,
  firstNeedUpdatePwd,
  flagNew,
  flagSecond,
  resetFormRef,
  resetRules,
  passWordConfig,
  pwdStrCheckList,
  verificationCode,
  verifyCodeShow
} = {...toRefs(state)} //绑定的数据
const {loginButton, nameChange, passwordChange, cancelReset, reset, changeCode, verifyCodeChange} = {...methods} //绑定方法
onMounted(()=>{
  methods.getCaptcha();
  document.addEventListener('keydown', methods.enterKeyDown, false);
})
onBeforeUnmount(()=>{
  document.removeEventListener('keydown', methods.enterKeyDown, false);
})
</script>

<style scoped lang="scss">
$w_lo: 1920;
$h_lo: 1080;
@function pxTvw_lo($px){
  @return calc(#{$px}/#{$w_lo}*100vw);
}
@function pxTvh_lo($px){
  @return calc(#{$px}/#{$h_lo}*100vh);
}

.login-content {
  @include wh100();
  @include add_bgImg();
  background-image: url("../../assets/img/login/back.jpg");
  :deep(.input-panel){
    width: 100%;
    height: pxTvh_lo(40);
    .el-input__wrapper{
      padding: 1px pxTvw_lo(11) 1px pxTvw_lo(20);
      .el-input__prefix{
        img {
          object-fit: contain;
          width: pxTvw_lo(18);
          height: pxTvw_lo(18);
        }
        .el-input__prefix-inner>:last-child{
          margin-right: pxTvw_lo(15);
        }
      }
      .el-input__suffix{
        img {
          object-fit: contain;
          width: pxTvw_lo(18);
          height: pxTvw_lo(18);
          cursor: pointer;
        }
        .el-input__suffix-inner>:first-child {
          margin-left: pxTvw_lo(8);
        }
      }
      .el-input__inner{
        height: pxTvh_lo(20);
        line-height:  pxTvh_lo(20);
        font-size: pxTvw_lo(14);
        font-family: Source Han Sans CN-Bold, Source Han Sans CN,sans-serif;
        font-weight: 400;
        color: #323B4B;
      }
      .el-input__inner::placeholder {
        font-weight: 400;
        color: #B0B7C3;
      }
    }
  }
  .error-input{
    width: 400px;
    height: pxTvh_lo(21);
    line-height: pxTvh_lo(21);
    font-size: pxTvw_lo(12);
    font-weight: 400;
    color: #FF5630;
  }
  .el-form-item{
    margin-bottom: 0;
  }
  &> .login-panel {
    width: pxTvw_lo(290);
    height: pxTvh_lo(351);
    position: fixed;
    top: pxTvh_lo(285);
    right: pxTvw_lo(310);
    font-family: Source Han Sans CN-Bold, Source Han Sans CN,sans-serif;
    background-color: #ffffff;
    padding: pxTvh_lo(48) pxTvw_lo(50) pxTvh_lo(70) pxTvw_lo(50);
    border-radius: 8px;
    &> .login-title {
      width: 100%;
      height: pxTvh_lo(39);
      line-height: pxTvh_lo(39);
      text-align: center;
      font-size: pxTvw_lo(22);
      font-weight: bold;
      color: #4C4B5E;
      margin-bottom: pxTvh_lo(40);
    }
    .userKey{
      margin-top: pxTvh_lo(8);
    }
    .verifyCode{
      margin-top: pxTvh_lo(21 + 8);
      img{
        cursor: pointer;
      }
    }
    .operation{
      display: flex;
      justify-content: space-between;
      padding: pxTvh_lo(24) 0 pxTvh_lo(40) 0;
      &> :deep(.el-checkbox){
        height: pxTvh_lo(21);
        .el-checkbox__label{
          font-size: pxTvw_lo(14);
          font-weight: 400;
        }
        .el-checkbox__inner{
          width: pxTvw_lo(14);
          height: pxTvw_lo(14);
          &::after{
            width: pxTvw_lo(3);
            height: pxTvw_lo(7);
            left: pxTvw_lo(4);
            top: pxTvw_lo(1);
          }
        }
      }
      &> .tips{
        text-align: right;
        height: pxTvh_lo(21);
        line-height: pxTvh_lo(21);
        font-size: pxTvw_lo(14);
        font-weight: 400;
        color: #377DFF;
      }
    }
    .el-button--primary{
      width: 100%;
      background: #377DFF;
      border-radius: 4px;
      height: pxTvh_lo(49);
      line-height: pxTvh_lo(49);
      font-size: pxTvw_lo(16);
      font-weight: bold;
      font-family: Source Han Sans CN-Bold, Source Han Sans CN,sans-serif;
    }
  }
  &> .login-first{
    width: pxTvw_lo(290);
    height: pxTvh_lo(351);
    position: fixed;
    top: pxTvh_lo(285);
    right: pxTvw_lo(310);
    font-family: Source Han Sans CN-Bold, Source Han Sans CN,sans-serif;
    background-color: #ffffff;
    padding: pxTvh_lo(68) pxTvw_lo(50) pxTvh_lo(50) pxTvw_lo(50);
    border-radius: 8px;
    .highlight{
      color: #FF5630;
    }
    &>.tips{
      height: pxTvh_lo(21);
      font-size: pxTvw_lo(14);
      font-weight: 400;
      color: #323B4B;
      margin-bottom: pxTvh_lo(16);
    }
    .newPassword{
      margin-top: pxTvh_lo(16);
    }
    .secondPassword{
      margin-top: pxTvh_lo(29);
    }
    .el-button{
      margin-top: pxTvh_lo(32);
      width: calc(50% - #{pxTvw_lo(8)});
      border-radius: 4px;
      height: pxTvh_lo(49);
      line-height: pxTvh_lo(49);
      font-size: pxTvw_lo(16);
      font-weight: bold;
      font-family: Source Han Sans CN-Bold, Source Han Sans CN,sans-serif;
    }
    .el-button--primary{
      background: #377DFF;
    }
    .el-button+.el-button {
      margin-left: pxTvw_lo(16);
    }
  }
}
</style>
